1 //+-----------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // Implements the main entry point of the PresentationShim used for hosting
7 // Windows Client Applications in the browser
15 // Ported Windows->DevDiv. See SourcesHistory.txt.
16 // 2009/08/xx-[....],[....]
17 // PresentationHost 'super-shim' refactoring. Defined ProcessCommandLine and renamed
18 // WinMain->DelegatedWinMain. Compiling the 'shim implementation' code into PHDLL.
19 // See overview in DLL\PresentationHostDll.nativeproj.
21 //------------------------------------------------------------------------
23 #include "Precompiled.hxx"
25 #include "LoRights.hxx"
26 #include "HostShim.hxx"
27 #include "ClassFactory.hxx"
28 #include "Version.hxx"
29 #include "WatsonReporting.hxx"
30 #include "ShimUtilities.hxx"
31 #include "..\inc\registry.hxx"
34 #define NO_HOST_TIMEOUT_SECONDS (10 * 60)
36 //******************************************************************************
40 //******************************************************************************
42 //CComModule _Module; - now using the one defined in DllMain.cxx
43 long g_ServerRefCount
;
45 DWORD g_dwCommandLineFlags
;
46 LPWSTR g_pswzDebugSecurityZoneURL
;
47 HANDLE g_hNoHostTimer_shim
;
50 //******************************************************************************
52 // DelegatedWinMain - invoked by PresentationHost.exe (shim)
54 //******************************************************************************
56 int PASCAL
DelegatedWinMain(__in HINSTANCE hInstance
,
57 __in_opt HINSTANCE hPrevInstance
,
58 __in_opt LPSTR lpCommandLine
,
63 // The heap setting and DEPPolicy are not set here since these are setup by PH.EXE shim.
64 // Thus, we have nothing to do here in that respect.
66 EventRegisterMicrosoft_Windows_WPF();
67 EventWriteWpfHostUm_WinMainStart();
69 BOOL bCoInitialized
= FALSE
;
71 WCHAR wzFileName
[PATH_BUFFER_SIZE
+ 1];
72 WCHAR wzEventName
[EVENT_SIZE
+ 1];
73 WCHAR wzDebugSecurityZoneURL
[DEBUGSECURITYZONEURL_BUFFER_SIZE
+ 1];
74 WCHAR wzDotApplicationURL
[INTERNET_MAX_URL_LENGTH
];
76 PLUID_AND_ATTRIBUTES pDisabledPrivileges
= NULL
;
77 DWORD dwDisabledPrivilegesCount
= 0;
79 g_dwCommandLineFlags
= FLAGS_NONE
;
81 // Check for the command line flags
82 CKHR(ParseCommandLine(&g_dwCommandLineFlags
, wzFileName
, PATH_BUFFER_SIZE
, wzEventName
, EVENT_SIZE
, wzDebugSecurityZoneURL
, DEBUGSECURITYZONEURL_BUFFER_SIZE
, wzDotApplicationURL
, INTERNET_MAX_URL_LENGTH
));
84 // Overloading PresentationHost.exe to assist in launching .application files
85 if (*wzDotApplicationURL
&& (g_dwCommandLineFlags
& FLAG_LAUNCHDOTAPPLICATION
))
87 CKHR(CoInitialize(NULL
));
88 bCoInitialized
= TRUE
;
89 LaunchClickOnceApplication(wzDotApplicationURL
);
93 // For the shell open scenario, invoke the browser and exit
94 if (*wzFileName
&& (FLAGS_NONE
== g_dwCommandLineFlags
))
96 CKHR(InvokeBrowser(wzFileName
));
97 g_exitCode
= ERROR_SUCCESS
;
100 if(*wzDebugSecurityZoneURL
&& (g_dwCommandLineFlags
& FLAG_DEBUGSECURITYZONEURL
))
102 g_pswzDebugSecurityZoneURL
= wzDebugSecurityZoneURL
;
105 // The code below checks to see if the process is running with admin privileges.
106 // If so, it will start a new instance of the process with the same arguments but
107 // with reduced privileges. We don't do this in case a debugger is attached or if
108 // we detect the process was created with a high integrity level (or above) by
109 // running IE elevated as a way to achieve full-trust operation.
110 BOOL isEmbedding
= (g_dwCommandLineFlags
& FLAG_EMBEDDING
);
111 BOOL isDebug
= (g_dwCommandLineFlags
& FLAG_DEBUG
) || IsDebuggerPresent();
113 if (isEmbedding
&& !isDebug
&& !IsPresentationHostHighIntegrity())
115 if (ERROR_SUCCESS
!= GetDisabledPrivileges(&pDisabledPrivileges
, &dwDisabledPrivilegesCount
))
117 g_exitCode
= ERROR_COULD_NOT_LAUNCH_RESTRICTED
;
121 Assert(dwDisabledPrivilegesCount
!= 0);
122 Assert(pDisabledPrivileges
!= NULL
);
124 if (!IsCurrentProcessRestricted(pDisabledPrivileges
, dwDisabledPrivilegesCount
)) // checks ShouldProcessBeRestricted
126 if (!LaunchRestrictedProcess(NULL
, pDisabledPrivileges
, dwDisabledPrivilegesCount
))
128 ReportActivationFaultAndTerminate(WPFHostError2HResult(ERROR_COULD_NOT_LAUNCH_RESTRICTED
));
130 g_exitCode
= ERROR_SUCCESS
;
134 // If we aren't exiting then we should clean up
135 if (pDisabledPrivileges
!= NULL
)
137 delete [] pDisabledPrivileges
;
138 pDisabledPrivileges
= NULL
;
142 (void)CheckRegistryAccess();
143 (void)CheckAppDataFolderAccess();
144 // The HRESULT is ignored. If the process exits at this point, IE will fall back on shell activation,
145 // which will lead to infinite relaunching... So, if the registry or file ACL prolem is detected,
146 // we send the Watson report and let ClickOnce deployment fail, which usually leads to the error page.
148 // Set up termination thread if we don't connect to the host
151 g_exitCode
= ERROR_NO_HOST_INIT_FAILED
;
152 DWORD dwTimeoutSeconds
= 0;
153 CKHR(GetRegistryDWORD(HKEY_LOCAL_MACHINE
, RegKey_WPF_Hosting
, RegValue_NoHostTimeoutSeconds
, dwTimeoutSeconds
, NO_HOST_TIMEOUT_SECONDS
));
154 g_hNoHostTimer_shim
= TerminateIfNoHost(dwTimeoutSeconds
);
155 CHECK_BOOL_FROM_WIN32(g_hNoHostTimer_shim
);
159 CKHR(CoInitialize(NULL
));
160 bCoInitialized
= TRUE
;
162 if (!(g_dwCommandLineFlags
& FLAG_EMBEDDING
))
165 g_exitCode
= ERROR_NO_COMMAND_SPECIFIED
;
169 CKHR(CClassFactory::RegisterClassObjects());
171 // Signal the event if one was specified
172 if (g_dwCommandLineFlags
& FLAG_EVENT
)
174 HANDLE hEvent
= OpenEvent(EVENT_MODIFY_STATE
, FALSE
, wzEventName
);
175 BOOL success
= hEvent
!= NULL
&& SetEvent(hEvent
);
183 g_exitCode
= ERROR_NO_EVENT
;
188 // For the VS debug scenario, invoke the browser
189 if (*wzFileName
&& (g_dwCommandLineFlags
& FLAG_DEBUG
))
191 CKHR(InvokeBrowser(wzFileName
));
194 EventWriteWpfHostUm_EnteringMessageLoop();
196 //The message loop will only exit when the main object gets destroyed.
198 while(GetMessage(&msg
, NULL
, 0, 0))
200 // Forward all messages; ForwardTranslateAccelerator is responsible for determining
201 // which messages are relevant to it.
202 CVersion
* pVersion
= CHostShim::GetValidVersion();
203 if (pVersion
&& pVersion
->IsAttached() && (pVersion
->ForwardTranslateAccelerator(&msg
) == NOERROR
))
208 TranslateMessage(&msg
);
209 DispatchMessage(&msg
);
213 CClassFactory::RevokeAllClassObjects();
215 if (pDisabledPrivileges
!= NULL
)
217 delete [] pDisabledPrivileges
;
218 pDisabledPrivileges
= NULL
;
224 CoEEShutDownCOM() is called to cleanly release RCWs (COM Runtime Callable Wrappers).
225 AppVerifier finds that "A COM Proxy was called from the wrong context". This presumably happens
226 because the Finalizer thread fails to switch to the object's right context and calls
227 IUnknown->Release() directly. See WOSB 1795776.
229 [....] says, "You should also call GetModuleHandle() on mscorwks.dll just to see if it is loaded. [...]
230 CoEEShutdownCOM will cause mscorwks.dll to be loaded even if no managed code has been run."
232 This patch may not be needed once PresentationHost is migrated to the DevDiv depot and starts
233 using the MSVCRT version matching the compiler.
235 if ((GetModuleHandle(L
"clr.dll") != NULL
) || (GetModuleHandle(L
"mscorwks.dll") != NULL
))
237 LegacyActivationShim::CoEEShutDownCOM();
243 // The only cases above where hr is set to failure code is while starting the app
244 // and if registration failed. If we successfully started the app, return 0
245 int retCode
= FAILED(hr
) ? hr
: g_exitCode
;
247 EventWriteWpfHostUm_WinMainEnd((DWORD
)retCode
);
252 // This is the export which is invoked by the shim implementation of
253 // PresentationHost.exe to call into the actual v4+ PresentationHost
255 extern "C" int __stdcall
ProcessCommandLine(__in HINSTANCE hInstance
,
256 __in_opt LPSTR lpCommandLine
,
259 return DelegatedWinMain(hInstance
, NULL
, lpCommandLine
, nCmdShow
);